package com.come4loves.core.comunicate.router;

import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelHandlerContext;

import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.annotation.PostConstruct;

import com.come4loves.core.comunicate.protocol.ByteBufSerializer;
import com.come4loves.core.comunicate.protocol.Response;
import com.come4loves.core.comunicate.router.annotation.Cmd;

/**
 * 模块处理句柄接口
 * 
 * @author ludd
 * 
 */
public abstract class RouterHandler {
	protected Logger LOGGER = LoggerFactory.getLogger(getClass());
	/**
	 * 方法映射列表
	 */
	private Map<Byte, Method> METHOD_MAPS = new HashMap<Byte, Method>();

	/**
	 * 命令映射列表
	 */
	private Map<Byte, Cmd> CMD_MAPS = new HashMap<Byte, Cmd>();
	
	/**
	 * 获取模块
	 * @param cmd
	 * @return
	 */
	public Method getMethod(byte cmd) {
		return METHOD_MAPS.get(cmd);
	}

	/**
	 * 获取命令注解
	 * @param cmd
	 * @return
	 */
	public Cmd getCmd(byte cmd) {
		return CMD_MAPS.get(cmd);
	}
	
	@PostConstruct
	private void init() {
		register();

		Method[] mList = this.getClass().getDeclaredMethods();
		for (Method m : mList) {
			Cmd c = m.getAnnotation(Cmd.class);
			if (c != null) {
				if (METHOD_MAPS.containsKey(c.id())) {
					throw new RuntimeException(String.format("cmd annontation:[%d] duplicated key", c.id()));
				}
				METHOD_MAPS.put(c.id(), m);
				CMD_MAPS.put(c.id(), c);

//				if (LOGGER.isDebugEnabled()) {
//					LOGGER.debug(String.format("add cmd success! module:[%s]  cmd:[%s]  methodname:[%s]", getModule(), c.Id(), m.toString()));
//				}
			}
		}
	}
	
	public void sessionWrite(final ChannelHandlerContext context, final Response response, ChannelFutureListener listener) {
		ChannelFuture f = context.writeAndFlush(response);
		f.addListener(listener);
		ChannelFutureListener future = channelFutureListener(context, response);
		if (future != null) {
			f.addListener(future);
		}
	}
	public void sessionWrite(final ChannelHandlerContext context, final Response response) {
		ChannelFuture f = context.writeAndFlush(response);
		ChannelFutureListener future = channelFutureListener(context, response);
		if (future != null) {
			f.addListener(future);
		}
	}
	
	protected abstract ChannelFutureListener channelFutureListener(ChannelHandlerContext ctx, Response response) ;	

	/**
	 * write
	 * @param session
	 * @param response
	 * @param packet
	 */
	public void sessionWrite(ChannelHandlerContext context, Response response, ByteBufSerializer buffer) {
		response.setValue(buffer.getBytes());
		sessionWrite(context, response);
	}
	public void sessionWrite(ChannelHandlerContext context, Response response, byte[] bytes) {
		response.setValue(bytes);
		sessionWrite(context, response);
	}
	
	/**
	 * get module
	 * @return
	 */
	public abstract byte getModule();
	
	/**
	 * 实现类调用注册当前handler
	 */
	public abstract void register();

}